跳到主要内容

CLI Options

typer.Option() works very similarly to typer.Argument(), but has some extra features that we'll see next.

help 说明

lastname: Annotated[str, typer.Option(help="Last name of person to greet.")] = "",
formal: Annotated[bool, typer.Option(help="Say hi formally.")] = False,
image-20240710145506582

show_default 的用法也和 CLI Arguments 一样

必选的 CLI Options

要使 CLI Options 变为必选,只需要去掉默认值即可

lastname: Annotated[str, typer.Option()]

image-20240710145909844

输入提示 prompt

当必填的 Option 缺失时,除了直接抛出错误之外,还可以使用 prompt=True 来提示用户输入

lastname: Annotated[str, typer.Option(prompt=True)]
image-20240710150243283

在 prompt 中传入提示字符串,对用户更友好

lastname: Annotated[str, typer.Option(prompt="Please tell me your last name")]
image-20240710150557708

二次确认提示

有时候,你想让用户再次确认输入,可以使用 confirmation_prompt=True

project_name: Annotated[str, typer.Option(prompt=True, confirmation_prompt=True)]
import typer
from typing_extensions import Annotated


def main(
project_name: Annotated[str, typer.Option(prompt=True, confirmation_prompt=True)],
):
print(f"Deleting project {project_name}")


if __name__ == "__main__":
typer.run(main)
image-20240710150642909

密码 prompt

使用 hide_input=True 来开启密码模式

    password: Annotated[
str, typer.Option(prompt=True, confirmation_prompt=True, hide_input=True)
],

image-20240710152610193

自定义 Option 名

默认的取名方式:user_name -> --user-name

当然可以自定义:

user_name: Annotated[str, typer.Option("--name")]

设置短名

A short name is a CLI option name with a single dash (-) instead of 2 (--) and a single letter, like -n instead of --name.

user_name: Annotated[str, typer.Option("--name", "-n")]
image-20240710153239631

如果只定义了一个短名的话,那么默认的长名也无法使用

user_name: Annotated[str, typer.Option("-n")]
image-20240710153327881

如果想在定义短名的同时保留默认的长名,那只能都显式地定义出来了

main(user_name: Annotated[str, typer.Option("--user-name", "-n")]

组合各 Option 的短名

短名之间可以写在一起:-h -s -> -hs / -hs

不过,后面带值的短名在合并时,需要写在最末端:

image-20240710153103154

你可以定义多个短名,然后组合在一起

import typer
from typing_extensions import Annotated


def main(
name: Annotated[str, typer.Option("--name", "-n")],
formal: Annotated[bool, typer.Option("--formal", "-f")] = False,
):
if formal:
print(f"Good day Ms. {name}.")
else:
print(f"Hello {name}")


if __name__ == "__main__":
typer.run(main)
image-20240710153833588

Callback and Context

更多细节详见:https://typer.tiangolo.com/tutorial/options/callback-and-context/

校验 Options

使用 callback 参数来校验 Options

from typing import Optional

import typer
from typing_extensions import Annotated


def name_callback(value: str):
if value != "Camila":
raise typer.BadParameter("Only Camila is allowed")
return value


def main(name: Annotated[Optional[str], typer.Option(callback=name_callback)] = None):
print(f"Hello {name}")


if __name__ == "__main__":
typer.run(main)

image-20240710154046584

展示版本信息

from typing import Optional

import typer
from typing_extensions import Annotated

__version__ = "0.1.0"


def version_callback(value: bool):
if value:
print(f"Awesome CLI Version: {__version__}")
raise typer.Exit()


def main(
name: Annotated[str, typer.Option()] = "World",
version: Annotated[
Optional[bool], typer.Option("--version", callback=version_callback)
] = None,
):
print(f"Hello {name}")


if __name__ == "__main__":
typer.run(main)

If the --version CLI option is passed, we get a value True in the callback.

Then we can print the version and raise typer.Exit() to make sure the program is terminated before anything else is executed.

We also declare the explicit CLI option name --version, because we don't want an automatic --no-version, it would look awkward.

is_eager

请看这个示例:

from typing import Optional

import typer
from typing_extensions import Annotated

__version__ = "0.1.0"


def version_callback(value: bool):
if value:
print(f"Awesome CLI Version: {__version__}")
raise typer.Exit()


def name_callback(name: str):
if name != "Camila":
raise typer.BadParameter("Only Camila is allowed")


def main(
name: Annotated[str, typer.Option(callback=name_callback)],
version: Annotated[
Optional[bool], typer.Option("--version", callback=version_callback)
] = None,
):
print(f"Hello {name}")


if __name__ == "__main__":
typer.run(main)

当我们执行以下命令时:

python main.py --name Rick --version

name 的 callback 函数会使程序提前退出,version 信息就展示不出来力

image-20240710155738045

For those cases, we can mark a CLI parameter (a CLI option or CLI argument) with is_eager=True.

That will tell Typer (actually Click) that it should process this CLI parameter before the others:

version: Annotated[
Optional[bool],
typer.Option("--version", callback=version_callback, is_eager=True),
] = None,
image-20240710160020508